ひとりNavigation API Advent Calendar 16日目
https://gyazo.com/44ebcab732b90fd171ca2521ed77c89e
Navigation APIが最近熱いので、じゃあNavigation APIを使ってルーターライブラリを作るよねということで作ったやつです。
PoC的な立ち位置ではあるけど要チェック(?)
https://github.com/uhyo/funstack-router/blob/master/docs/FUNSTACK_Router_Hero_small.png?raw=true
PoC段階なので本番環境での使用はまだ推奨されていない code:js
import { Router, route, Outlet } from "@funstack/router";
// Define your page components
function Home() {
return <h1>Welcome Home</h1>;
}
function About() {
return <h1>About Us</h1>;
}
function Layout() {
return (
<div>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
<Outlet />
</div>
);
}
// Define your routes
const routes = [
route({
path: "/",
component: Layout,
children: [
route({ path: "/", component: Home }),
route({ path: "/about", component: About }),
],
}),
];
// Render the router
function App() {
return <Router routes={routes} />;
}
Outletがどういう仕組みなのだろうか
では内部実装を見ていこう
NavigationAPIAdapter
StaticAdapter
For unsupported browsers, use the fallback="static" option on the Router component, which renders matched routes without SPA navigation capabilities (links cause full page loads). サイト自体もfallback="static"にしていた
デフォルトは「fallback なし」なので後方互換性を維持 Static Pre-renderingをするには設定ファイルを弄る必要あり
今後の検討事項
初回ロード:Router 初回レンダー時に loader 実行
ナビゲーション時:navigation.intercept() 内で即実行
code:js
navigation.addEventListener("navigate", (event) => {
event.intercept({
handler: async () => {
matchRoutes() for destination URL
↓
Execute loaders, write to cache ← Starts immediately!
}
})
});
loader結果のキャッシュ戦略
navigation entry key + route path をキーにキャッシュ 履歴移動(戻る/進む)では同じ entry key が使われるため、即座にキャッシュヒット code:cache
Navigate to /users/1 → entry key "abc" → loader runs, cached
Navigate to /users/2 → entry key "def" → loader runs, cached
Press Back → entry key "abc" → cache HIT, no loader execution
Press Forward → entry key "def" → cache HIT, no loader execution
code:tsx
function UserDetail({ data, params }: { data: Promise<User>; params: { userId: string } }) {
const user = use(data); // Component chooses when to suspend
return <div>{user.name} (ID: {params.userId})</div>;
}
主な機能
addEventListener / removeEventListener
updateCurrentEntry
navigate
canGoBack / canGoForward
履歴の前後移動が可能かどうかを判定
goBack / goForward
実際にページ前・後へ移動する操作
React Routerの構成は基本的に倣ってるけどデータロード機構・キャッシュ戦略、静的レンダリングは独自の設計になっていて差別化されていた